#include "gdi.h"
#include "stdint.h"
#include "font.h"
#include "math.h"
#include "lcd_driver.h"
#include "stdlib.h"
#include "frgui.h"


Gdi *pGdi;
char gdiBuffer[64][108];//< gdi buffer
/** @brief constructor */
Gdi::Gdi()
{
    int i;
    lcd_driver.open(&lcd_driver);
    for(i=0; i<sizeof(gdiBuffer); i++)
    {
        *((char*)gdiBuffer +i) =0;
    }
    
    needRefresh =0;
}
/** @brief desstructor */
Gdi::~Gdi()
{
}

/** @brief operator 'delete' definitions  */ 
void Gdi::operator delete(void *t)
{
    port_free(t);
}

/** @brief operator 'new' definitions  */ 
void *Gdi::operator new(unsigned int len)
{
   return port_malloc(len);
}

/** @brief dirty 
 * @param short x 
 * @param short y 
 * @param short x1 
 * @param short y1
 * @note
 */
void Gdi::dirty(short x, short y, short x1, short y1)
{
    needRefresh =1;
    paintRect(x, y, x1,y1);
}

/** @brief draw point 
 * @param short x0 
 * @param short y0 
 * @param char value
 * @note
 */
void Gdi::drawPoint(short x0, short y0, char value)
{
    char t_char;
    t_char =gdiBuffer[y0][x0/2];
    
    if(x0&1)
    {
        gdiBuffer[y0][x0/2] = (t_char &0xF0) | (value&0x0F);
    }else
    {
        gdiBuffer[y0][x0/2] = (t_char &0x0F) | ((value&0x0F)<<4);
    }
}

/** @brief reverse point 
 * @param short x0 
 * @param short y0 
 * @note
 */
void Gdi::reversePoint(short x0, short y0)
{
    char t_char;
    t_char =gdiBuffer[y0][x0/2];
    
    if(x0&1)
    {
        gdiBuffer[y0][x0/2] = t_char ^0x0F;
    }else
    {
        gdiBuffer[y0][x0/2] = t_char ^0xF0;
    }
}

/** @brief Draw a rectangular
 * @param short x0 
 * @param short y0
 * @param short x1
 * @param short y1
 * @note
 */
void Gdi::paintRect(short x0, short y0, short x1, short y1)
{
    short w,h;
    short y;

    w=x1-x0;
    h =y1-y0;
    
    for(y=y0; y<y0+h; y++)
    {
        //every byte holds 2 dots;
        //offset is set to x/3
        lcd_driver.ioControl(&lcd_driver, IO_CONTROL_LCD_SET_XY, (y<<8) + 2*(x0/6) );
        lcd_driver.write( &lcd_driver, &gdiBuffer[y][(x0-(x0%6))/2], w/2+4, 0);
    }
}

/** @brief refresh
 * @note
 */
void Gdi::refresh()
{
    if(needRefresh)
    {
        needRefresh =0;
        paintRect(0,0, RESX, RESY);
    }
}
/*
void Gdi::fillRect(short x0, short y0, short x1, short y1, char value)
{
	short x,y;
	for(x=x0; x<x0+x1; x++)
	{
		for(y=y0; y<y0+y1; y++)
		{
			drawPoint(x,y,value);
		}
	}
}

void Gdi::reverseRect(short x0, short y0, short x1, short y1)
{
	short x,y;
	for(x=x0 ; x<x0+x1; x++)
	{
		for(y=y0; y<y0+y1; y++)
		{
			reversePoint(x,y);
		}
	}
}

void Gdi::drawRect(short x0, short y0, short x1, short y1, char value)
{   
    short x,y;
	for(x=x0; x<x0+x1;x++)
	{
		for(y=y0; y<y0+y1;y++)
		{
			if( (x==x0) || (y==y0) || (x==x0+x1-1) || (y==y0+y1-1))
			{
				drawPoint(x,y,value);
			}else{
				//drawPoint(x,y,0);
			}
		}
	}
}
*/


/**
 * draw a x*y size font,
* y0:x0                  x1
*    B0 B1
*    B2 B3
*    B4 B5
* yn:x0.................x1
*/
/*
void Gdi::drawFont(short x0, short y0, char *pchar, char valueB,char valueW, FONT* font)
{
    char t_char;
    short t_y, t_x;
    
    char *pCharFont;
    pCharFont =FONT_ADDR(*pchar);
	
	for(  t_y=y0; t_y<y0+font->height; t_y+=8)
	{
        t_x =x0;

        fillRect(t_x,t_y, 1,font->height, valueW);
        t_x++;

		for( ; t_x<x0+font->width+1; t_x++)
		{
		    short y;
            t_char =*pCharFont++;
			for( y=t_y; y<y0+font->height; y++)
			{
			    drawPoint(t_x,y,t_char &1?valueB:valueW);
				t_char >>=1;
			}

		}
        //t_x++;
        fillRect(t_x, t_y,1,font->height, valueW);
	}
}

void Gdi::drawLine(short x0, short y0, short x1, short y1, char value)
{
    short x,y;
    int k;
    
    if(x0<x1)
    {
        x =x0;
    }
    else
    {
        x =x1;
        x1 =x0;
        x0 =x;
    }
    
    if(y0<y1)
    {
        y=y0;
    }
    else
    {
        y =y1;
        y1 =y0;
        y0 =y;
    }
    
    k = RESX*RESY*(y1-y0)/(x1-x0);
    for(x=x0; x<=x1; x++)
    {
        for(y=y0; y<=y1; y++)
        {
            if(y ==((x-x0)*k)/(RESX*RESY) + y0)
            {
                drawPoint(x,y,value);
            }
        }
    }
}
*/
/** @brief draw a circle from (x0,y0) to (x1,y1), with circle high=d
 *         input[x0,y0],[x1,y1], as start point, cosa=(a^2+b^2 -c^)/2ab,
 *         ugly circle, might be improved
 */
 /*
#define PI          (3.14159265358979323846f)

void Gdi::drawCircle(short x0, short y0, short x1, short y1, float cosa, char value)
{
    int x,y;
    float asqr,bsqr,csqr;

    #if 0
    csqr = (x1-x0)*(x1-x0) + (y1-y0)*(y1-y0);
    for(x=x0; x<=x1; x++)
    {
        
        for(y =y0; y<=y1; y++)
        {
            asqr = (x-x0)*(x-x0) + (y-y0)*(y-y0);
            bsqr = (x1-x)*(x1-x) + (y1-y)*(y1-y);
            
            if((int)sqrt(csqr) == (int)sqrt(asqr + bsqr -2* sqrt(asqr*bsqr)*cosa) )
            {
                drawPoint(x,y, value);
                break;
            }
        }
    }
    #endif
}
*/
/*
void Gdi::drawBlank(short x0, short y0, short w, short h, char valueW)
{
    int t_x;
    int t_y;
    
    for(t_y =y0; t_y< y0+h; t_y++)
    {
        for(t_x=x0; t_x< x0+w; t_x++)
        {
            drawPoint(t_x,t_y, valueW);
        }
    }
}
*/
/*
void Gdi::drawString(short x0, short y0, short w, short h, char *str, char valueB,char valueW, FONT *font)
{
    int t_int;
    char *pchar;

    pchar =str;
    t_int =0;
    while(*pchar){
        if( (t_int+font->width) >w) break;
        drawFont( x0+t_int, y0, pchar, valueB,valueW, font);
		t_int += font->width +1;
        pchar ++;
    }
}

void Gdi::drawBmp(short x0, short y0, char *pbmp, short w, short h)
{
    short t_x,t_y;
    char *pchar =pbmp;
	char t_char;
	
	for( t_y=y0; t_y<y0+h; t_y+=8)
	{
		for( t_x=x0; t_x<x0+w; t_x++)
		{
		    short y;
				t_char =*pchar++;
				for( y=t_y; y<y0+h; y++)
				{
					drawPoint(t_x,y,t_char &1);
					t_char >>=1;
				}

		}
	}
}
*/

